package cn.itsource.ymcc.service.impl;

import cn.itsource.exception.CustomGlobalException;
import cn.itsource.util.AssertUtil;
import cn.itsource.util.StrUtils;
import cn.itsource.util.VerifyCodeUtils;
import cn.itsource.ymcc.constant.RedisConstant;
import cn.itsource.ymcc.domain.MessageSms;
import cn.itsource.ymcc.dto.SmsRedisValueDTO;
import cn.itsource.ymcc.enmus.CustomExceptionEnum;
import cn.itsource.ymcc.dto.SendSmsCodeDTO;
import cn.itsource.ymcc.mapper.MessageSmsMapper;
import cn.itsource.ymcc.service.IVerifyCodeService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    //必须加泛型  加了后才会去用序列化的配置
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired  //这里也可以用@Resource
    private MessageSmsMapper messageSmsMapper;

    @Override
    public void sendSmsCode(SendSmsCodeDTO dto) {
        //1、非空校验  在controller里面已经校验过了
        //2、判断图片验证码是否正确 不正确就抛异常
        AssertUtil.isTrue(checkImageCode(dto), CustomExceptionEnum.IMG_CODE_FALSE.getMessage(),CustomExceptionEnum.IMG_CODE_FALSE.getCode());

        //3、Redis里检查该用户是否已经存在验证码
        String redisKey = RedisConstant.SMS_REDIS_KEY_PREFIX+dto.getMobile();//拼接Redis中的key
        SmsRedisValueDTO smsRedisValueDTO = (SmsRedisValueDTO)redisTemplate.opsForValue().get(redisKey);//用redisKey去Redis中去找这个手机号的验证码
        if(smsRedisValueDTO != null){
            //校验短信验证码是否过期 如果短信验证码没过期，就抛异常请勿频繁发送短信验证码  （存入Redis短信验证码的时间）
            AssertUtil.isTrue((System.currentTimeMillis() - smsRedisValueDTO.getCreateDate().getTime()) > RedisConstant.SMS_SEND_INTERVAL,CustomExceptionEnum.SEND_OFFEN.getMessage(),CustomExceptionEnum.SEND_OFFEN.getCode());
        }
            //短信验证码过期就发送短信验证码  并保存短信验证码的发送时间
        SmsRedisValueDTO valueDTO = smsRedisValueDTO.builder().code(StrUtils.getRandomString(RedisConstant.SMS_SEND_CODE_LENGTH)).createDate(new Date()).build();
            //将短信验证码保存到Redis中去 并设置短信验证码的过期时间为5分钟
        redisTemplate.opsForValue().set(redisKey,valueDTO,RedisConstant.SMS_SEND_EXPIRE, TimeUnit.MINUTES);

        //4、 将信息保存到数据库
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("注册的短信验证码");
        messageSms.setContent("验证码是:"+valueDTO.getCode());

        //获取请求的ip  //这个是固定的写法
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String ip = requestAttributes.getRequest().getRemoteAddr();
        messageSms.setIp(ip);
        messageSms.setSendTime(new Date());

        //添加保存到数据库
        messageSmsMapper.insert(messageSms);

        //5、调用第三方api发送短信(自己调)
        System.out.println(messageSms.getContent());


    }

//    private boolean checkImageCode(String imageCodeKey) {
//
//        // 如果imageCodeKey是111  那么就认为图片验证码错误
//        if (StringUtils.equals(imageCodeKey,"111")) {
//            return false;
//        }
//        return true;
//    }

    private boolean checkImageCode(SendSmsCodeDTO dto) {

            Object imageCode = redisTemplate.opsForValue().get(dto.getImageCodeKey());//到Redis中去查询imagecode  还需要非空校验
        //        if(imageCode == null){
        //
        //        }

            // 判断Redis中的图片验证码和传入的图片验证码是否相同
                if (!imageCode.toString().equalsIgnoreCase(dto.getImageCode())) {
                return false;
                }
                return true;
    }



    @Override
    public String image(String uuid) {
        //1.校验空值
        if (StringUtils.isEmpty(uuid)){
            throw  new CustomGlobalException("传入数据异常","4040");
        }
        //2.随机生成字符串
        String randomString = StrUtils.getComplexRandomString(4);
        //3.redis保存随机生成字符串
        redisTemplate.opsForValue().set(uuid,randomString,5, TimeUnit.MINUTES);
        //4.生成验证码图片base64加密后的字符串
        String s = VerifyCodeUtils.verifyCode(100, 50, randomString);
        return s;
    }


}
